//---------------------------------------------------------------------
//  This file is part of the Background Motion solution.
// 
//  Copyright (C) Mindscape (TM).  All rights reserved.
//  http://www.mindscape.co.nz
// 
//  THIS CODE AND INFORMATION ARE PROVIDED AS IS WITHOUT WARRANTY OF ANY
//  KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
//  IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
//  PARTICULAR PURPOSE.
//---------------------------------------------------------------------

using System;
using System.ComponentModel;
using System.Security.Principal;
using System.Web;

using Mindscape.BackgroundMotion.Core;

namespace Mindscape.BackgroundMotion.Website.Infrastructure
{
  internal class HttpContextAdapter : IContext
  {
    /// <summary>
    /// Returns a value held in the session container
    /// </summary>
    /// <typeparam name="T">The generic type of the returned object</typeparam>
    /// <param name="key">The key to the object</param>
    /// <returns>An object of type T which is known by the requested key</returns>
    public T GetSession<T>(string key)
    {
      return (T)HttpContext.Current.Session[key];
    }

    /// <summary>
    /// Returns a value held in the "query string" parameter container
    /// </summary>
    /// <typeparam name="T">The generic type of the returned object</typeparam>
    /// <param name="key">The key to the object</param>
    /// <returns>An object of type T which is known by the requested key</returns>
    public T GetParameter<T>(string key)
    {
      string stringValue = GetParameter(key);
      T value = default(T);

      if (!string.IsNullOrEmpty(stringValue))
      {
        TypeConverter typeConverter = TypeDescriptor.GetConverter(typeof(T));

        if (typeConverter.CanConvertFrom(typeof(string)))
        {
          try
          {
            value = (T)typeConverter.ConvertFromString(stringValue);
          }
          catch
          {
          }
        }
      }

      return value;
    }

    /// <summary>
    /// Returns a value held in the "query string" parameter container
    /// </summary>
    /// <param name="key">The key to the object</param>
    /// <returns>An string which is known by the requested key</returns>
    public string GetParameter(string key)
    {
      return HttpContext.Current.Request.QueryString.Get(key);
    }

    /// <summary>
    /// Assigns a new cookie to the cookies collection
    /// </summary>
    /// <param name="name">The name of the cookie</param>
    /// <param name="value">The value of the cookie</param>
    /// <param name="expires">The time at which the cookie expires</param>
    public void AddCookie(string name, string value, DateTime expires)
    {
      HttpCookie cookie = new HttpCookie(name, value);
      cookie.Expires = expires;
      cookie.HttpOnly = true;

      HttpContext.Current.Response.Cookies.Add(cookie);
    }

    /// <summary>
    /// Removes a cookie from the cookies collection by a nominated name
    /// </summary>
    /// <param name="name">The name of the cookie</param>
    public void RemoveCookie(string name)
    {
      AddCookie(name, "Expiring", DateTime.Now.AddYears(-30));
    }

    /// <summary>
    /// Returns a cookie value from the cookies collection by a nominated name
    /// </summary>
    /// <param name="name">The name of the cookie</param>
    /// <returns>The value of the cookie which is known by the nominated name</returns>
    public string GetCookie(string name)
    {
      HttpCookie cookie = HttpContext.Current.Request.Cookies[name];

      if (cookie != null)
      {
        return cookie.Value;
      }

      return null;
    }

    /// <summary>
    /// The principal which is currently authorised in this context
    /// </summary>
    public IPrincipal User
    {
      get { return HttpContext.Current.User; }
      set { HttpContext.Current.User = value; }
    }

    /// <summary>
    /// Returns the Path and Querystring of the current request
    /// </summary>
    public string RequestPathAndQuery
    {
      get { return HttpContext.Current.Request.Url.PathAndQuery; }
    }

    /// <summary>
    /// Returns the Absolute Path of the current request
    /// </summary>
    public string RequestAbsolutePath
    {
      get { return HttpContext.Current.Request.Url.AbsolutePath; }
    }

    /// <summary>
    /// Assigns a value to the session container under a nominated key
    /// </summary>
    /// <typeparam name="T">The generic type of the assigned object</typeparam>
    /// <param name="key">The key to the object</param>
    /// <param name="value">The object</param>
    public void SetSession<T>(string key, T value)
    {
      HttpContext.Current.Session[key] = value;
    }

    /// <summary>
    /// Removes an object from the session container which matches a nominated key
    /// </summary>
    /// <param name="key">The key to the object</param>
    public void RemoveSession(string key)
    {
      HttpContext.Current.Session.Remove(key);
    }

    /// <summary>
    /// Redirects to a nominated URL
    /// </summary>
    /// <param name="url">The URL to redirect to</param>
    public void RedirectTo(string url)
    {
      HttpContext.Current.Response.Redirect(url);
    }

    /// <summary>
    /// Redirects to a nominated URL and querystring
    /// </summary>
    /// <param name="url">The URL to redirect to</param>
    /// <param name="parameters">The querystring parameters to pass</param>
    public void RedirectTo(string url, params string[] parameters)
    {
      string queryString = null;

      if ((parameters != null) && (parameters.Length > 0))
      {
        queryString = "?" + parameters[0];

        for (int i = 1; i < parameters.Length; i++)
        {
          queryString += "&" + parameters[i];
        }
      }

      RedirectTo(url + queryString);
    }

    /// <summary>
    /// Returns an item from the current context container
    /// </summary>
    /// <typeparam name="T">The generic type of the object</typeparam>
    /// <param name="key">The key to the object</param>
    /// <returns>The object</returns>
    public T GetItem<T>(string key)
    {
      return (T)HttpContext.Current.Items[key];
    }

    /// <summary>
    /// Assigns an item into the current context container
    /// </summary>
    /// <typeparam name="T">The generic type of the assigned object</typeparam>
    /// <param name="key">The key to the object</param>
    /// <param name="value">The object</param>
    public void SetItem<T>(string key, T value)
    {
      HttpContext.Current.Items[key] = value;
    }

    /// <summary>
    /// Removes an item from the current context container
    /// </summary>
    /// <param name="key">The key to the object</param>
    public void RemoveItem(string key)
    {
      HttpContext.Current.Items.Remove(key);
    }
  }
}